package com.luxk.db.data.table;

import com.luxk.db.data.ByteObject;
import com.luxk.util.ByteArrayUtil;
import java.io.IOException;

public class ByteObjectTableRow extends ByteObject implements Row {
	
	public final int MAX_LOCK_BYTE = 0xFF;
	public final int MAX_COLUMN_COUNT = 0xFF;
	
	private static final int POS_LOCKBYTE = 0;      //  1 byte
	private static final int POS_FLAGS = 1;         //  1 byte
	private static final int POS_COLUMN_COUNT = 2;  //  1 byte
	private static final int POS_CHAIN_ROWID = 3;   // 10 bytes if exists
	private static final int POS_COLUMN_START_UNCHAIN = 3;
	private static final int POS_COLUMN_START_CHAIN = 13;
	
	private static final int FLAG_DELETED = 0x01;
	private static final int FLAG_HEAD_ROW = 0x02;
	private static final int FLAG_CHAINED = 0x04;
	
	private byte lockByte = Byte.MAX_VALUE;
	private byte flags = Byte.MAX_VALUE;
	private int columeCount = -1;
	private int length = -1;

	public int getColumnCount() throws IOException {
		if(this.columeCount == -1) {
			if(this.rawBytes != null) {
				this.columeCount = ByteArrayUtil.readUnsignedByte(
						this.rawBytes, POS_COLUMN_COUNT);
				assert(this.columeCount <= MAX_COLUMN_COUNT);
			}
		}
		return columeCount;
	}
	public int getLength() {
		return length;
	}
	public boolean isDeleted() {
		if(this.flags == Byte.MAX_VALUE) {
			if(this.rawBytes != null) {
				this.flags = this.rawBytes[this.offset + POS_FLAGS];
			}
		}
		return (this.flags & FLAG_DELETED) != 0;
	}
	public boolean isHeadRow() {
		if(this.flags == Byte.MAX_VALUE) {
			if(this.rawBytes != null) {
				this.flags = this.rawBytes[this.offset + POS_FLAGS];
			}
		}
		return (this.flags & FLAG_HEAD_ROW) != 0;
	}
	public boolean hasChainRow() {
		if(this.flags == Byte.MAX_VALUE) {
			if(this.rawBytes != null) {
				this.flags = this.rawBytes[this.offset + POS_FLAGS];
			}
			
		}
		return (this.flags & FLAG_CHAINED) != 0;
	}
	public Object getChainRowid() {
		if(!hasChainRow())
			return null;
		
		byte[] ret = new byte[10];
		System.arraycopy(this.rawBytes, this.offset + POS_CHAIN_ROWID,
				ret, 0, ret.length);
		
		return ret;
	}
	public Row getChainRow() {
		return null;
	}
	public Column[] getAllColumn() {
		return null;
	}
	public Column getColumn(int colIdx) {
		return null;
	}

	protected void deserialize() throws IOException {
		if(this.rawBytes == null)
			throw new IOException("ByteObjectTableRow not initialized");
		
		this.lockByte = this.rawBytes[this.offset + POS_LOCKBYTE];
		this.flags = this.rawBytes[this.offset + POS_FLAGS];
		this.columeCount = ByteArrayUtil.readUnsignedByte(
				this.rawBytes, POS_COLUMN_COUNT);
		
		assert(this.lockByte <= MAX_LOCK_BYTE);
		assert(this.columeCount <= MAX_COLUMN_COUNT);
		assert(this.flags <= (FLAG_DELETED |FLAG_HEAD_ROW |FLAG_CHAINED));
	}
	public String dump() {
		return null;
	}
	
	public byte getLockByte() throws IOException {
		if(this.rawBytes == null) {
			throw new IOException("ByteObjectTableRow not initialized");
		}
		if(this.lockByte == Byte.MAX_VALUE) {
			this.lockByte = this.rawBytes[this.offset + POS_LOCKBYTE];
		}
		return this.lockByte;
	}
}
